home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Applications / QuArK / plugins / mergepolys.py < prev    next >
Text File  |  2004-01-05  |  6KB  |  177 lines

  1.  
  2. ########################################################
  3. #
  4. #              Poly Merging Code
  5. #
  6. #  formerly in maptagside, now called from there
  7. #
  8. #  tiglari@planetquake.com, April 15, 2001
  9. #
  10. #######################################
  11.  
  12. # Header: $
  13.  
  14. import quarkx
  15. import quarkpy.mapentities
  16. from tagging import *
  17. from faceutils import *
  18.  
  19. def closenough(vtx,vtx1):
  20.     if abs(vtx-vtx1) < 1:
  21.         return 1
  22.     else: return 0
  23.  
  24.  
  25. def same_vertices(face,tagged):
  26.     "face and tagged must have one vtx set which must be the same"
  27.     facevtx = face.vertices[0]
  28.     tagvtx = tagged.vertices[0]
  29.     length = len(facevtx)
  30.     if length!=len(tagvtx):
  31.         return 0
  32.     for fvtx in facevtx:
  33.         for tvtx in tagvtx:
  34.             if closenough(fvtx,tvtx):
  35.                 break
  36.         else: return 0
  37.     return 1
  38.   
  39. def useableby(face, poly):
  40.     newface=face.copy()
  41. #
  42. #   wtf doesn't this work?
  43. #
  44. #   newpoly=poly.copy()
  45. #   newpoly.appenditem(newface)
  46. #   newpoly.rebuildall()
  47. #   squawk(`len(newpoly.faces)`)
  48.     newpoly = quarkx.newobj("test:p")
  49.     for face2 in poly.faces:
  50.         newpoly.appenditem(face2.copy())
  51.     newpoly.appenditem(newface)
  52.     for face2 in newpoly.faces:
  53. #      squawk("checking")
  54.         if newface==face2:
  55.             return 1
  56.     return 0
  57.  
  58.  
  59. #
  60. # poly1 can be merged with poly2 at face of poly1,
  61. #   returning result or None
  62. #
  63. def mergeable(tagged, poly1, o):
  64.  
  65.     def noncoplanar(poly, face):
  66.         for f in poly.faces:
  67.             if coplanar(f, face):
  68.                return 0
  69.         return 1
  70.  
  71.     for face in o.faces:
  72.         if len(face.faceof)!=1 or not coplanar(face,tagged): continue
  73.         if face.normal*tagged.normal>0: continue
  74.         if same_vertices(face,tagged): 
  75.             new = quarkx.newobj(o.name)
  76.             for oldface in o.subitems: # not faces, we don't mess with shared faces
  77.                 if oldface==face or oldface.type!=":f": continue
  78.                 new.appenditem(oldface.copy())
  79.             #
  80.             # the merged poly will be in o's group, so we need to copy
  81.             # all the faces.  any facees used by the tagged faces's
  82.             # poly that are actually used by o will not be ok.
  83.             #
  84.             for tagface in poly1.faces:
  85.                 if noncoplanar(o,tagface): # ys
  86.                     new.appenditem(tagface.copy())
  87.                     #
  88.                     # If it can be added to o and still be used by
  89.                     # o, then it changes the shape of o and merger 
  90.                     # should not be enabled
  91.                     #
  92.           #          squawk("testing useability")
  93.                     if useableby(tagface, o):  # if it can be added to
  94.           #             squawk("passed")
  95.                          return None
  96.             return new
  97.  
  98. #
  99. # merge a poly to one with a tagged face
  100. #
  101. def MergePolyClick(m):
  102.     editor=mapeditor()
  103.     if editor is None: return
  104.     undo = quarkx.action()
  105.     undo.exchange(m.o, m.result)
  106.     undo.exchange(m.tagged.faceof[0], None)
  107.     editor.ok(undo,"merge polys")
  108.  
  109. #
  110. # makes menu item, put on menu in maptagside
  111. #
  112. def mergepoly(editor,o):
  113.     item = qmenu.item("Merge Polys",MergePolyClick,"|This command can merge two brushes which `kiss' at a face, meaning that the faces have the same location, orientation, size and shape, but are oriented in opposite directions.\n\nTo use it, tag one of the kissing faces, then select the brush that contains the other.  If this menu item becomes enabled, the operation is then supposed to be able to combine the two brushes into one.  The selected brush will be `dominant', in that the resulting brush will be in its position of the group structure, and its textures and higher shared faces will be retained where relevant.\n\nIf the operation will change the overall shape, or create an invalid brush, this menu item is supposed to remain disabled.")
  114.     item.state=qmenu.disabled
  115.     tagged=gettagged(editor)
  116.     if tagged is None or len(tagged.faceof)!=1:
  117.         return item
  118.     new = mergeable(tagged,tagged.faceof[0],o)
  119.     if new is not None:
  120.         item.tagged=tagged
  121. #            item.face=face
  122.         item.state=qmenu.normal
  123.         item.result=new
  124.         item.o=o
  125.     return item
  126.  
  127.  
  128. def MergePolysInGroup(group):
  129.     newgroup = group.copy()
  130.     done = 'done' # to be used as a loop-break exception
  131.     while 1:
  132.         try:
  133.             faces=newgroup.findallsubitems("",":f")
  134.             polys = newgroup.findallsubitems("",":p")
  135.             for face in faces:
  136.                 if len(face.faceof)==1:
  137.                     poly1 = face.faceof[0]
  138.                     for poly2 in polys:
  139.                         if poly2 is poly1:
  140.                             continue
  141.                         newpoly = mergeable(face, poly1, poly2)
  142.                         if newpoly is not None:
  143.                             poly2.parent.appenditem(newpoly)
  144.                             poly2.parent.removeitem(poly2)
  145.                             poly1.parent.removeitem(poly1)
  146.                             raise done
  147.         except done:
  148.             pass
  149.         else:
  150.             break
  151.             
  152.     return newgroup
  153.  
  154. #
  155. # merge the mergeable polys in a group.
  156. #
  157. def MergePolysClick(m):
  158.     editor = mapeditor()
  159.     if editor is None: return
  160.     undo = quarkx.action()
  161.     new = MergePolysInGroup(m.o)
  162.     undo.exchange(m.o, new)
  163.     editor.ok(undo,"merge polys in group")
  164.     
  165. #
  166. # makes menu item, put on menu in maptagside
  167. #
  168. def groupmergepoly(editor,o):
  169.     item = qmenu.item("Merge Polys",MergePolysClick,"|This command will try to merge all mergeable polys in the group.\n\mIt doesn't necessarily get the best answer, if you think you can do better, you can use Merge Polys on the face menu.")
  170.     item.o=o
  171.     return item
  172.  
  173. # $Log: mergepolys.py,v $
  174. # Revision 1.1  2001/04/15 08:53:44  tiglari
  175. # move merge poly code to mergepolys.py; add merge polys in group functionality
  176. #
  177.